package services

import (
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"github.com/pkg/errors"
	"time"
	"weiboxs.com/new_h_glasses/models"
	"weiboxs.com/new_h_glasses/utils"
)

type EntryreturnService struct {
	Id           int64
	Number       string
	Remarks      string
	Suppliers    int64
	Postage      float64
	CreatedAt    int64
	UpdatedAt    int64
	CreatedBy    string
	UpdatedBy    string
	PayMethod    int
	DeliveryMode int

	Rowsnum      string
	Rowsdata     []map[string]interface{}
	DepartmentId int64
}

type EntryreturnTempFormPost struct {
	MiddleId   int64 `json:"middle_id"`
	Invid      int64 `json:"invid"`
	SndId      int64 `json:"snd_id"`
	ReserveNum int64 `json:"reserve_num"`
	ReturnNum  int64 `json:"return_num"`
	EntryId    int64 `json:"entry_id"`
	GoodsId    int64 `json:"goods_id"`
}

//开始冲红出库
func (s *EntryreturnService) SaveFlushing(cur *models.BackendUser, flowing_id int64) error {
	if flowing_id == 0 {
		return errors.New("参数错误")
	}
	if cur.DepartmentId == 0 {
		return errors.New("隶属参数错误")
	}
	//读取入库记录
	flwing, err := models.GeErpFlowingById(flowing_id)
	if err != nil {
		return err
	}
	if flwing.Typeid != 1 {
		return errors.New("入库单据类型不正确")
	}
	//读取入库明细记录
	flowing_data := models.ErpFlowingDataListForFlowingId(flowing_id)
	if len(flowing_data) <= 0 {
		return errors.New("没有明细记录")
	}
	flSer := new(ErpFlowingService)
	to,_ := orm.NewOrm().Begin()
	flwing.Id = 0
	flwing.Typeid = 2
	flwing.FlowingUser = cur.RealName
	flwing.FlowingDate = time.Now().Unix()
	flwing.NumberUpNo = flwing.Number
	if err := flSer.SaveErpFlowing(to, flwing); err != nil {
		to.Rollback()
		return err
	}

	new_flowing_data := make([]*models.ErpFlowingData, 0)
	invSer := new(ErpInventoryService)

	for k, _ := range flowing_data {
		value := flowing_data[k]
		//开始出库操作
		queryInv := invSer.QueryInventoryOne(value.InventoryId, "")
		checkInvNumber := queryInv.Inventory - value.StorageNum;
		if checkInvNumber < 0 {
			to.Rollback()
			return errors.New("产品库存不足")
		}

		//判断商品是否在盘点中
		if err := StocksCheckIng(value.Products.Id, cur); err != nil {
			to.Rollback()
			return err
		}

		if err := invSer.UpdateErpInventory(to, queryInv, (0 - value.StorageNum)); err != nil {
			to.Rollback()
			return err
		}
		//出库结束
		value.Id = 0
		value.Typeid = 2 //确定冲红类型
		value.PurchaseUpNo = flwing.NumberUpNo
		value.InventoryId = queryInv.Id
		value.PrimaryStorageNum = queryInv.Inventory
		value.Snd = queryInv.Snd
		new_flowing_data = append(new_flowing_data, value)
	}
	//保存冲红明细
	if err := flSer.SaveErpFlowingData(to, flwing, new_flowing_data); err != nil {
		to.Rollback()
		return err
	}
	//处理原入库明细
	if _, err := to.Update(&models.ErpFlowing{Id: flowing_id, IsFlushing: 1}, "IsFlushing"); err != nil {
		to.Rollback()
		return err
	}
	//更新入库单状态
	if _, err := to.Update(&models.ErpEntry{Id: flwing.Entry.Id, Auditing: 3}, "Auditing"); err != nil {
		to.Rollback()
		return err
	}
	to.Commit()
	return nil
}

func CreateEntryreturnNumber() string {
	stat := utils.GetDateParse(time.Now().Format("2006-01-02"))
	end := stat + 86400
	return fmt.Sprintf("%s%06d", time.Now().Format("20060102150405"), models.QueryErpEntryreturnTimeSoltSeterCount(stat, end, )+1)
}

//写入单据信息202005
func (s *EntryreturnService) ErpEntryFormInsert(isTemp int) (int64, error) {

	entry := new(models.ErpEntryreturn)
	entry.Auditing = 0
	entry.Money = 0
	entry.ProNumber = 0
	entry.DepartmentId = s.DepartmentId
	entry.Postage = s.Postage
	entry.CreatedAt = s.CreatedAt
	entry.UpdatedAt = time.Now().Unix()
	entry.CreatedBy = s.CreatedBy
	entry.UpdatedBy = s.UpdatedBy
	entry.UpdatedAt = s.UpdatedAt
	entry.PayMethod = s.PayMethod
	entry.DeliveryMode = s.DeliveryMode
	entry.Number = s.Number
	entry.Remarks = s.Remarks
	entry.Suppliers = &models.ErpSuppliers{Id: s.Suppliers}

	orm := orm.NewOrm()
	var err error
	//添加主表数据
	_, err = orm.Insert(entry)
	if err != nil {
		return 0, err
	}
	return entry.Id, err
}

//修改数据2020-05
func (s *EntryreturnService) ErpEntryFormUpdate() error {

	entry := new(models.ErpEntryreturn)
	entry.Id = s.Id
	entry.UpdatedAt = time.Now().Unix()
	entry.UpdatedBy = s.UpdatedBy
	entry.Number = s.Number
	entry.Remarks = s.Remarks
	entry.Suppliers = &models.ErpSuppliers{Id: s.Suppliers} //增加供应商
	entry.Postage = s.Postage

	to,_ := orm.NewOrm().Begin()

	var err error

	if _, err = to.Update(entry, "updated_at", "updated_by", "number", "remarks", "pro_number", "money", "postage", "suppliers_id"); err != nil {
		to.Rollback()
		return err
	}

	to.Commit()

	return nil
}

//查看数据202005
func ErpEntryreturnView(id, depid int64) (*models.ErpEntryreturn, error) {
	var err error
	orm := orm.NewOrm()
	//获取主表信息
	entry := new(models.ErpEntryreturn)
	err = orm.QueryTable(models.ErpEntryreturnTableName()).RelatedSel("Suppliers").Filter("department_id", depid).Filter("id", id).One(entry)
	if err != nil {
		return nil, err
	}
	return entry, nil
}

//写入退货明细
func (s *EntryreturnService) InsertEntryreturnEntryData(data []*EntryreturnTempFormPost) (int64, error) {
	if len(data) <= 0 {
		return 0, errors.New("请选择退货商品信息")
	}
	to,_ := orm.NewOrm().Begin()
	middle := new(models.ErpEntryreturnMiddle)

	//处理中间表数据
	first := data[0]
	if first.Invid <= 0 {
		return 0, errors.New("订单信息出错")
	}
	//设置中间表数据
	middle.Products = &models.ErpProducts{Id: first.GoodsId}
	middle.EntryId = first.EntryId
	middle.Attribute = ""
	middle.Id = first.MiddleId
	if first.MiddleId <= 0 { //不存在
		if _, err := to.Insert(middle); err != nil {
			return 0, err
		}
	} else { //存在中间表，则删除明细表内容
		if _, err := to.Raw("DELETE FROM "+models.ErpEntryreturnDataTableName()+" WHERE middle_id=?", first.MiddleId).Exec(); err != nil {
			return 0, err
		}
	}
	var entry_datas = make([]*models.ErpEntryreturnData, 0)
	for k, _ := range data {
		value := data[k];
		if value.ReturnNum <= 0 {
			to.Rollback()
			return 0, errors.New("退货数量不能小于或的等于0")
		}
		if value.ReserveNum < value.ReturnNum {
			to.Rollback()
			return 0, errors.New("退货数量不能大于库存数量")
		}
		inv := new(models.ErpInventory)
		to.QueryTable(models.ErpInventoryTableName()).Filter("id__eq", value.Invid).One(inv)
		if inv.Id == 0 || inv.Inventory <= 0 {
			to.Rollback()
			return 0, errors.New("商品库存信息不存在")
		}

		//写入明细表
		entry_data := new(models.ErpEntryreturnData)
		entry_data.Entry = &models.ErpEntryreturn{Id: value.EntryId}
		entry_data.Products = inv.Products
		entry_data.Acceptance = inv.Acceptance
		entry_data.InventoryId = inv.Id
		entry_data.Amount = value.ReturnNum
		entry_data.Snd = &models.ErpProductsSnd{Id: value.SndId}
		entry_data.MiddleId = middle.Id
		entry_datas = append(entry_datas, entry_data)

		middle.PurchaseNum += entry_data.Amount //计算中间表数量
	}
	//更新中间表产品数量
	if _, err := to.Update(middle, "PurchaseNum"); err != nil { //更新数量
		to.Rollback()
		return 0, errors.New("产品数量更新失败")
	}
	//批量执行
	if _, err := to.InsertMulti(len(entry_datas), entry_datas); err != nil {
		to.Rollback()
		return 0, err
	}
	to.Commit()
	return middle.Id, nil
}

//确认保存
func (s *EntryreturnService) EntryreturnSubmitOrder(depid int64, entry_id int64) error {
	o := orm.NewOrm()

	erpentry, _ := models.GetErpEntryreturnById(entry_id)
	if erpentry.Id == 0 || erpentry.DepartmentId != depid {
		return errors.New("找不到数据")
	}
	//获取
	ertry_data := make([]*models.ErpEntryreturnData, 0)
	if _, err := o.QueryTable(models.ErpEntryreturnDataTableName()).Filter("entry_id", erpentry.Id).All(&ertry_data); err != nil {
		return err
	}
	var (
		pro_number int64 //产品数量
	)
	for key, _ := range ertry_data {
		value := ertry_data[key]
		pro_number += value.Amount //总产品数量
	}
	erpentry.Auditing = 1
	erpentry.ProNumber = pro_number
	if err := erpentry.ErpEntryreturnEdit("ProNumber", "Auditing"); err != nil {
		return err
	}
	return nil
}

//按中间表ID获取退货明细
func (s *EntryreturnService) GetMiddleDataForEntry(middle_id int64) ([]*models.ErpEntryreturnData, error) {
	if (middle_id == 0) {
		return nil, errors.New("参数错误")
	}
	entry_data := make([]*models.ErpEntryreturnData, 0)

	orm.NewOrm().QueryTable(models.ErpEntryreturnDataTableName()).RelatedSel("Acceptance", "Products").Filter("middle_id__eq", middle_id).Limit(-1).All(&entry_data)

	return entry_data, nil
}

//删除指定出入库记录
func ErpEntryreturnDelete(id int64) error {
	to,_ := orm.NewOrm().Begin()

	entry := &models.ErpEntryreturn{Id: id}

	if err := to.Read(entry); err != nil { //查询是否存在记录信息
		to.Rollback()
		return err
	}

	if entry.Auditing != 0 {
		return errors.New("已通过审核的数据不允许删除")
	}

	//删除副表内容
	if _, err := to.QueryTable(models.ErpEntryreturnDataTableName()).Filter("entry_id", id).Delete(); err != nil {
		to.Rollback()
		return err
	}

	if _, err := to.Delete(entry); err != nil {
		to.Rollback()
		return err
	}

	to.Commit()

	return nil
}

//删除中间数据2020-05
func (s *EntryreturnService) DeleteMiddleData(middle_id int64) error {

	to,_ := orm.NewOrm().Begin()

	middle := &models.ErpEntryreturnMiddle{Id: middle_id}
	if err := to.Read(middle); err != nil {
		return err
	}
	if _, err := to.Delete(middle); err != nil { //删除中间数据
		return err
	}
	if _, err := to.Raw("DELETE FROM "+models.ErpEntryreturnDataTableName()+" WHERE middle_id=?", middle_id).Exec(); err != nil { //删除明细表
		to.Rollback()
		return err
	}
	to.Commit()

	return nil
}

//开始确认出库
func (s *EntryreturnService) ConfirmEntryOut(cur *models.BackendUser, entry_id int64) error {
	entry_return := new(models.ErpEntryreturn)
	to,_ := orm.NewOrm().Begin()
	entry_return.Id = entry_id
	err := to.Read(entry_return)
	if err != nil {
		return err
	}
	if entry_return.DepartmentId != cur.DepartmentId {
		return errors.New("找不到单据信息")
	}
	if entry_return.Auditing == 2 || entry_return.Auditing == 0 {
		return errors.New("单据不允许操作")
	}

	//获取退库明细
	entry_return_data := models.ErpEntryreturnDataList(entry_id)
	if len(entry_return_data) <= 0 {
		return errors.New("没有可用的退库信息")
	}
	//流水明细
	flowingData := make([]*models.ErpFlowingData, 0)
	invSer := new(ErpInventoryService)
	//开始处理退库
	for k, _ := range entry_return_data {
		value := entry_return_data[k];
		inv := new(models.ErpInventory)
		to.QueryTable(models.ErpInventoryTableName()).Filter("id__eq", value.InventoryId).One(inv)
		if inv.Id == 0 || inv.Inventory <= 0 {
			to.Rollback()
			return errors.New("商品库存信息不存在或库存为0")
		}
		//判断商品是否在盘点中
		if err := StocksCheckIng(value.Products.Id, cur); err != nil {
			to.Rollback()
			return err
		}
		primaryStorageNum := inv.Inventory
		//更新库存
		if err := invSer.UpdateErpInventory(to, inv, (0 - value.Amount)); err != nil {
			to.Rollback()
			return err
		}

		//设置流水明细
		flowing := new(models.ErpFlowingData)
		flowing.Typeid = 3 //退货出库
		flowing.DepartmentId = inv.DepartmentId
		flowing.Products = inv.Products
		flowing.Acceptance = inv.Acceptance
		flowing.Snd = inv.Snd
		flowing.InventoryId = inv.Id
		flowing.PrimaryStorageNum = primaryStorageNum
		flowing.StorageNum = value.Amount
		flowing.PurchaseUpNo = entry_return.Number
		flowingData = append(flowingData, flowing)
	}

	//入库记录
	//写入流水明细
	flSer := new(ErpFlowingService)
	if err := flSer.SaveErpFlowingData(to, &models.ErpFlowing{Id: 0}, flowingData); err != nil {
		to.Rollback()
		return err
	}
	//更新退库主表状态
	entry_return.Auditing = 2
	entry_return.OutDate = time.Now().Format("2006-01-02")
	entry_return.OutUser = cur.RealName
	if _, err := to.Update(entry_return, "Auditing", "OutDate", "OutUser"); err != nil {
		to.Rollback()
		return err
	}

	to.Commit()
	return nil
}
